﻿#include "myopenglwidget.h"

unsigned int VAO, VBO, EBO;
unsigned int shaderProgram, shaderProgram2;
float vertices1[] = {  // 画一个三角形
    -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f};

float vertices2[] = {  // 画矩形
    0.5f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f,
    // -0.5f,0.5f,0.0f,
    // 0.5f,-0.5f,0.0f,
    -0.5f, -0.5f, 0.0f, -0.5f, 0.5f, 0.0f};

float vertices[] = {  // 画两个三角形
    -0.9f, -0.5f, 0.0f, 0.0f, -0.5f, 0.0f, -0.45f, 0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.9f, -0.5f, 0.0f, 0.45f, 0.5f, 0.0f};

unsigned int VBOs[2], VAOs[2];  // 画两个三角形，使用不同的VBO和VAO
float firstTriangle[] = {       // 画两个三角形
    0.0f, -0.5f, 0.0f, 0.9f, -0.5f, 0.0f, 0.45f, 0.5f, 0.0f};

float secondTriangle[] = {
    // 画两个三角形
    -0.9f, -0.5f, 0.0f, 0.0f, -0.5f, 0.0f, -0.45f, 0.5f, 0.0f,
};

unsigned int indices[] = {0, 1, 3, 1, 2, 3};  // 需要画的点

const char* vertexShaderSource = "#version 330 core\n"
                                 "layout (location = 0) in vec3 aPos;\n"
                                 "void main()\n"
                                 "{\n"
                                 " gl_Position = vec4(aPos.x,aPos.y,aPos.z,1.0);\n"
                                 "}\0";

const char* fragmentShaderSource = "#version 330 core\n"
                                   "out vec4 FragColor;\n"
                                   "void main()\n"
                                   "{\n"
                                   " FragColor = vec4(1.0f,0.5f,0.2f,1.0f);\n"
                                   "}\n\0";

const char* fragmentShader2Source = "#version 330 core\n"
                                    "out vec4 FragColor;\n"
                                    "void main()\n"
                                    "{\n"
                                    " FragColor = vec4(1.0f,01.0f,0.0f,1.0f);\n"
                                    "}\n\0";

MyOpenGLWidget::MyOpenGLWidget(QWidget* parent) : QOpenGLWidget(parent) {}

MyOpenGLWidget::~MyOpenGLWidget() {
    glDeleteVertexArrays(2, VAOs);  // 删除顶底和着色器
    glDeleteShader(shaderProgram);
    glDeleteShader(shaderProgram2);
}

void MyOpenGLWidget::initializeGL() {
    initializeOpenGLFunctions();  // 本地的指针初始化

    // 创建VAO VBO，并赋予对象ID
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    // 一次创建多个VAO,VBO
    glGenVertexArrays(2, VAOs);
    glGenBuffers(2, VBOs);
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);

    /*
        绑定第一个属性值
    */
    // 绑定VBO VAO

    glBindVertexArray(VAOs[0]);
    glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);

    // 为当前绑定到target的缓冲区对象创建一个新的数据存储
    // 如果data不是null，则使用来自此指针的数据初始化数据存储
    //    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
    glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle), firstTriangle, GL_STATIC_DRAW);

    // 告诉显卡如何解析缓冲区的属性值
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

    // 开启一个VAO管理的第一个属性值
    glEnableVertexAttribArray(0);  // vaos[0]的属性值

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    //    glBindVertexArray(0);

    /*
        绑定第二个属性值
    */
    // 绑定VBO VAO
    glBindVertexArray(VAOs[1]);
    glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);

    // 为当前绑定到target的缓冲区对象创建一个新的数据存储
    // 如果data不是null，则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER, sizeof(secondTriangle), secondTriangle, GL_STATIC_DRAW);

    // 告诉显卡如何解析缓冲区的属性值
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

    // 开启一个VAO管理的第一个属性值
    glEnableVertexAttribArray(0);  // vaos[1]的属性值

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    //    glBindVertexArray(0);

    // 顶点着色器
    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    glCompileShader(vertexShader);

    // 片段着色器
    unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    glCompileShader(fragmentShader);

    unsigned int fragmentShader2 = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader2, 1, &fragmentShader2Source, nullptr);
    glCompileShader(fragmentShader2);

    // 链接
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    shaderProgram2 = glCreateProgram();
    glAttachShader(shaderProgram2, vertexShader);
    glAttachShader(shaderProgram2, fragmentShader2);
    glLinkProgram(shaderProgram2);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);// 设置线条填充
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glBindVertexArray(0);

    glDeleteShader(fragmentShader);
    glDeleteShader(fragmentShader2);
}

void MyOpenGLWidget::resizeGL(int w, int h) {
    Q_UNUSED(w);
    Q_UNUSED(h);
    glViewport(0, 0, w, h);
}

void MyOpenGLWidget::paintGL() {
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(shaderProgram);  // 使用着色器

    //    glBindVertexArray(VAO);// 绑定的画图对象
    //    glDrawArrays(GL_TRIANGLES,0,3);
    // glDrawArrays(GL_TRIANGLES,0,6);
    //    glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,&indices);// 画矩形
    //     glDrawArrays(GL_TRIANGLES,0,6);// 画两个三角形

    /*
        两个不一样的VAO
    */
    glBindVertexArray(VAOs[0]);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    glUseProgram(shaderProgram2);  // 使用着色器
    glBindVertexArray(VAOs[1]);
    glDrawArrays(GL_TRIANGLES, 0, 3);
}
